﻿namespace HZY.Framework.DependencyInjection.Services;

/// <summary>
/// 服务提供者工厂
/// </summary>
public class AutowiredServiceProviderFactory : IServiceProviderFactory<IServiceCollection>
{
    public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
    {
        // 把服务替换成委托服务
        for (int i = 0; i < containerBuilder.Count; i++)
        {
            var item = containerBuilder[i];

            // 判断类型是否继承了 IAopServiceProvider
            if (typeof(IAopServiceProvider).IsAssignableFrom(item.ServiceType) ||
                (item.ImplementationType is not null && typeof(IAopServiceProvider).IsAssignableFrom(item.ImplementationType)))
            {
                var serviceDescriptor = new ServiceDescriptor(item.ServiceType, sp =>
                {
                    var impl = (item.ImplementationType is null ?
                        ActivatorUtilities.CreateInstance(sp, item.ServiceType) :
                        ActivatorUtilities.CreateInstance(sp, item.ImplementationType)) as IAopServiceProvider;

                    impl!.ServiceProvider = sp;

                    return impl;
                }, item.Lifetime);

                containerBuilder.Replace(serviceDescriptor);
            }
        }

        var serviceProvider = containerBuilder.BuildServiceProvider();
        return new AutowiredServiceProvider(serviceProvider);
    }

    IServiceCollection IServiceProviderFactory<IServiceCollection>.CreateBuilder(IServiceCollection services)
    {
        if (services == null) return new ServiceCollection();
        return services;
    }

    ///// <summary>
    ///// 获取 IServiceProvider
    ///// </summary>
    ///// <param name="context"></param>
    ///// <param name="type"></param>
    ///// <returns></returns>
    //protected virtual IServiceProvider? SetServiceProvider(object? obj, Type? type = null)
    //{
    //    // 检测类型是否继承了 IAutowiredServiceProvider
    //    if (context.Target is IAopServiceProvider autowiredServiceProvider)
    //    {
    //        return autowiredServiceProvider.ServiceProvider;
    //    }

    //    var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;

    //    IServiceProvider? serviceProvider = null;

    //    try
    //    {
    //        type ??= context.Target?.GetType();

    //        if (type is null) return serviceProvider;

    //        foreach (var item in type.GetProperties(flags))
    //        {
    //            if (item.PropertyType == typeof(IServiceProvider))
    //            {
    //                serviceProvider = item.GetValue(context.Target) as IServiceProvider;
    //                break;
    //            }
    //        }

    //        foreach (var item in type.GetFields(flags))
    //        {
    //            if (item.FieldType == typeof(IServiceProvider))
    //            {
    //                serviceProvider = item.GetValue(context.Target) as IServiceProvider;
    //                break;
    //            }
    //        }

    //        if (serviceProvider is not null)
    //        {
    //            return serviceProvider;
    //        }

    //        if (type.BaseType is null)
    //        {
    //            return serviceProvider;
    //        }

    //        return this.GetServiceProvider(context, type.BaseType);
    //    }
    //    catch (Exception)
    //    {
    //        return serviceProvider;
    //    }
    //}
}
